package simpledb.tx;

import simpledb.server.SimpleDB;
import simpledb.buffer.*;
import java.util.*;

/**
 * Manages the transaction's currently-pinned buffers. 
 * @author Edward Sciore
 */
class BufferList {
	private Map<Integer,Buffer> buffers = new HashMap<Integer,Buffer>();
	private List<Integer> pins = new ArrayList<Integer>();
	private BufferMgr bufferMgr = SimpleDB.bufferMgr();

	/**
	 * Returns the buffer pinned to the specified block.
	 * The method returns null if the transaction has not
	 * pinned the block.
	 * @param blk a reference to the disk block
	 * @return the buffer pinned to that block
	 */
	Buffer getBuffer(int blk) {
		return buffers.get(blk);
	}

	/**
	 * Pins the block and keeps track of the buffer internally.
	 * @param blk a reference to the disk block
	 */
	void pin(int blk) {
		Buffer buff = bufferMgr.pin(blk);
		buffers.put(blk, buff);
		pins.add(blk);
	}

	/**
	 * Appends a new block to the specified file
	 * and pins it.
	 * @param filename the name of the file
	 * @param fmtr the formatter used to initialize the new page
	 * @return a reference to the newly-created block
	 */
	int pinNew(String filename, PageFormatter fmtr) {
		Buffer buff = bufferMgr.pinNew(fmtr);
		int blk = buff.block();
		buffers.put(blk, buff);
		pins.add(blk);
		return blk;
	}

	/**
	 * Unpins the specified block.
	 * @param blk a reference to the disk block
	 */
	void unpin(int blk) {
		Buffer buff = buffers.get(blk);
		bufferMgr.unpin(buff);
		pins.remove(new Integer(blk));
		if (!pins.contains(blk))
			buffers.remove(blk);
	}

	/**
	 * Unpins any buffers still pinned by this transaction.
	 * @param txnum the id of the transaction
	 */
	void unpinAll(int txnum) {
		for (int blk : pins) {
			Buffer buff = buffers.get(blk);
			bufferMgr.unpin(buff);
		}
		buffers.clear();
		pins.clear();
	}
}